package cc.rengu.igas.route.core.helper;

import cc.rengu.igas.route.common.constant.SmartRouteParamConstant;
import cc.rengu.igas.route.common.dao.OpmsBankSupportCfgMapper;
import cc.rengu.igas.route.common.dao.impl.OpmsBankSupportCfgMapperImpl;
import cc.rengu.igas.route.common.entity.OpmsBankSupportCfgInfo;
import cc.rengu.igas.route.common.enums.*;
import cc.rengu.igas.route.core.model.CompleteRouteInfoBean;
import cc.rengu.igas.route.core.model.DstChannelFilterModel;
import cc.rengu.igas.route.core.model.RouterReq;
import cc.rengu.igas.share.common.dao.HolidayInfoMapper;
import cc.rengu.igas.share.common.dao.impl.HolidayInfoMapperImpl;
import cc.rengu.igas.share.core.realize.PublicService;
import cc.rengu.igas.share.core.realize.impl.PublicServiceImpl;
import cc.rengu.oltp.service.common.constant.AppParamConstant;
import cc.rengu.oltp.service.common.constant.TreeNodeConstant;
import cc.rengu.oltp.service.common.dao.DstChannelInfoMapper;
import cc.rengu.oltp.service.common.dao.DstTxnAuthCfgMapper;
import cc.rengu.oltp.service.common.dao.ChannelCallCfgMapper;
import cc.rengu.oltp.service.common.dao.impl.DstChannelInfoMapperImpl;
import cc.rengu.oltp.service.common.dao.impl.DstTxnAuthCfgMapperImpl;
import cc.rengu.oltp.service.common.dao.impl.ChannelCallCfgMapperImpl;
import cc.rengu.oltp.service.common.entity.DstChannelInfo;
import cc.rengu.oltp.service.common.entity.DstTxnAuthCfg;
import cc.rengu.oltp.service.common.entity.SysParam;
import cc.rengu.oltp.service.common.entity.ChannelCallCfg;
import cc.rengu.oltp.service.model.BizException;
import cc.rengu.oltp.service.realize.SysParamService;
import cc.rengu.oltp.service.realize.impl.SysParamServiceImpl;
import cc.rengu.oltp.utility.util.AmountUtil;
import cc.rengu.oltp.utility.util.DateUtil;
import cc.rengu.oltp.utility.util.RedisUtil;
import cc.rengu.oltp.utility.util.XmlTreeUtil;
import cc.rengu.utility.base.StringUtil;
import cc.rengu.utility.log.RgLog;
import cc.rengu.utility.log.RgLogger;
import com.alibaba.fastjson.JSON;

import java.util.List;
import java.util.Optional;

/**
 * 路由操作
 *
 * @author xionglz
 * @version 1.0
 * @date 2020-05-08
 */
public class RouterHelper {

    /**
     * 根据阻断性条件判断通道是否可用
     *
     * @param dstChannelFilterModel 渠道过滤信息
     * @return boolean true渠道检查通过 false检查不通过
     * @throws Exception 其他错误及异常
     * @author xionglz
     * @date 2020-04-27
     */
    public static boolean dstChannelFilter(DstChannelFilterModel dstChannelFilterModel, CompleteRouteInfoBean completeRouteInfoBean) throws Exception {
        RgLogger rglog = RgLog.getLogger(RouterHelper.class.getName());
        //校验通道权限
        if (!judgeDstChannel(completeRouteInfoBean.getDstChannelInfo(), rglog)) {
            rglog.warn("通道<{}>权限检查不通过", dstChannelFilterModel.getDstChannelId());
            return false;
        }

        //校验通道交易权限
        if (!judgeTxnAuth(dstChannelFilterModel, completeRouteInfoBean.getDstTxnAuthCfg(), rglog)) {
            rglog.warn("通道<{}>交易权限检查不通过", dstChannelFilterModel.getDstChannelId());
            return false;
        }

        //营业时间检查
        if (!judgeOpenTime(completeRouteInfoBean.getDstChannelInfo(), completeRouteInfoBean.getDstTxnAuthCfg(), rglog)) {
            rglog.warn("通道<{}>交易营业时间检查不通过", dstChannelFilterModel.getDstChannelId());
            return false;
        }

        //校验对手行是否在支持的银行卡列表中
        if (!judgeBankNo(dstChannelFilterModel.getOpenBankNo(), dstChannelFilterModel.getInstId(), dstChannelFilterModel.getDstChannelId(), dstChannelFilterModel.getTransAmt(), rglog)) {
            rglog.warn("通道<{}:{}>对手行<{}>不在支持的银行列表", dstChannelFilterModel.getDstChannelId(),
                    completeRouteInfoBean.getDstChannelInfo().getDstChannelName(), dstChannelFilterModel.getOpenBankNo());
            return false;
        }

        //校验账户类型是否在支持的列表中
        if (!judgeAcctType(dstChannelFilterModel.getAcctType(), completeRouteInfoBean.getDstChannelInfo().getSupportAcctType())) {
            rglog.warn("通道<{}:{}>支持账户类型位图<{}>中未配置支持该类型<{}>账户", dstChannelFilterModel.getDstChannelId(),
                    completeRouteInfoBean.getDstChannelInfo().getDstChannelName(), completeRouteInfoBean.getDstChannelInfo().getSupportAcctType(), dstChannelFilterModel.getAcctType());
            return false;
        }

        //限额检查
        return judgeAmtLimit(dstChannelFilterModel, completeRouteInfoBean, rglog);
    }

    /**
     * 检查通道代收付鉴权交易权限
     *
     * @param dstChannelInfo 通道信息
     * @param rglog          日志句柄
     * @return true检查通过 false检查不通过
     */
    private static boolean judgeDstChannel(DstChannelInfo dstChannelInfo, RgLogger rglog) {
        if (!SmartRouteParamConstant.YES.equalsIgnoreCase(dstChannelInfo.getDstChannelStatus()) ||
                !SmartRouteParamConstant.YES.equalsIgnoreCase(dstChannelInfo.getIntelligentRouteFlag())) {
            rglog.warn("通道<{}>不支持智能路由<{}>或者未启用<{}>", dstChannelInfo.getDstChannelId(),
                    dstChannelInfo.getIntelligentRouteFlag(), dstChannelInfo.getDstChannelStatus());
            return false;
        }
        return true;
    }

    /**
     * 检查通道代收付鉴权交易权限
     *
     * @param dstChannelFilterModel 通道过滤对象
     * @param dstTxnAuthCfg         通道交易权限信息
     * @param rglog                 日志句柄
     * @return true检查通过 false检查不通过
     */
    private static boolean judgeTxnAuth(DstChannelFilterModel dstChannelFilterModel, DstTxnAuthCfg dstTxnAuthCfg,
                                        RgLogger rglog) {
        if (null == dstChannelFilterModel) {
            rglog.warn("通道过滤请求信息为空");
            return false;
        }
        if (null == dstTxnAuthCfg) {
            rglog.warn("通道交易权限信息为空");
            return false;
        }
        if (!AppParamConstant.YES.equalsIgnoreCase(dstTxnAuthCfg.getSupportFlag())) {
            rglog.warn("支付通道<{}>不支持此渠道交易分组<{}> 通道交易码:<{}>", dstChannelFilterModel.getDstChannelId(),
                    dstChannelFilterModel.getTxnGroup());
            return false;
        }

        if (!AppParamConstant.YES.equalsIgnoreCase(dstTxnAuthCfg.getIntelligentRouteFlag())) {
            rglog.warn("支付通道<{}>通道交易码:<{}>不支持智能路由", dstChannelFilterModel.getDstChannelId(),
                    dstTxnAuthCfg.getIntelligentRouteFlag());
            return false;
        }
        return true;
    }

    /**
     * 检查通道营业时间
     *
     * @param dstTxnAuthCfg 通道交易权限信息
     * @param rglog         日志句柄
     * @return true检查通过 false检查不通过
     * @throws Exception 其他异常抛出
     */
    private static boolean judgeOpenTime(DstChannelInfo dstChannelInfo, DstTxnAuthCfg dstTxnAuthCfg, RgLogger rglog) throws Exception {
        if (null == dstTxnAuthCfg || null == dstChannelInfo) {
            rglog.warn("通道或通道交易权限信息为空");
            return false;
        }

        String currDate = DateUtil.getCurrentDate();
        String currTime = DateUtil.getCurrentTime();
        //存在业务开始日期，未到营业开始日期
        if (!StringUtil.isNullorEmpty(dstChannelInfo.getBizStartDate())) {
            if (Integer.parseInt(currDate) < Integer.parseInt(dstChannelInfo.getBizStartDate())) {
                rglog.warn("当前<{}>未到营业日期<{}>", currDate, dstChannelInfo.getBizStartDate());
                return false;
            }
        } else {
            rglog.debug("营业开始日期为空不检查", dstChannelInfo.getBizStartDate());
        }
        //不设置默认为自然日
        if (StringUtil.isNullorEmpty(dstChannelInfo.getBizCtrlRule())) {
            dstChannelInfo.setBizCtrlRule(SmartRouteParamConstant.NATURE_DAY);
        }
        //只使用通道的日期类型字段即业务控制类型字段
        //检查当前日期是否为法定工作日
        if (SmartRouteParamConstant.WORK_DAY.equals(dstChannelInfo.getBizCtrlRule())) {
            rglog.debug("工作日检查", dstChannelInfo.getBizCtrlRule());
            HolidayInfoMapper holidayInfoMapper = new HolidayInfoMapperImpl();
            if (holidayInfoMapper.isHoliday(currDate)) {
                rglog.warn("当前<{}>为节假日，通道不营业<{}:{}>", currDate, dstChannelInfo.getDstChannelId(), dstChannelInfo.getDstChannelName());
                return false;
            }
            rglog.debug("当前日期<{}><{}:{}>工作日检查通过", currDate, dstChannelInfo.getDstChannelId(), dstChannelInfo.getDstChannelName());
        } else {
            rglog.debug("自然日不检查", dstChannelInfo.getBizCtrlRule());
        }
        //交易的营业日期不为空且不等于* 则检查通道交易营业时间不检查通道营业时间
        if (!StringUtil.isNullorEmpty(dstTxnAuthCfg.getSupportBeginTime()) && !SmartRouteParamConstant.TIME_ALL.equals(dstTxnAuthCfg.getSupportBeginTime())) {
            //营业开始时间 表示从0点开始
            //0-相等，小于0-开始日期日期小于当前日期，大于0-开始日期大于当前日期
            if (DateUtil.compareTime(dstTxnAuthCfg.getSupportBeginTime(), currTime, SmartRouteParamConstant.FORMAT_DATE_TIME6) > 0) {
                rglog.warn("通道交易<{}:{}>当前<{}>未到营业开始时间<{}>", dstTxnAuthCfg.getMsgDstId(), dstTxnAuthCfg.getTxnName(), currTime, dstTxnAuthCfg.getSupportBeginTime());
                return false;
            }
            rglog.debug("通道交易<{}:{}>当前时间<{}>营业开始时间<{}>检查通过", dstTxnAuthCfg.getMsgDstId(), dstTxnAuthCfg.getTxnName(), currTime, dstTxnAuthCfg.getSupportBeginTime());
        }
        //交易的营业日期为空或者等于* 则检查通道营业时间
        else {
            rglog.debug("通道交易<{}:{}>当前时间<{}>营业开始时间为<{}>不检查通道交易，检查通道", dstTxnAuthCfg.getMsgDstId(), dstTxnAuthCfg.getTxnName(), currTime, dstTxnAuthCfg.getSupportBeginTime());
            //通道存在开始时间则检查
            if (!StringUtil.isNullorEmpty(dstChannelInfo.getBizStartTime()) && !SmartRouteParamConstant.TIME_ALL.equals(dstChannelInfo.getBizStartTime())) {
                //0-相等，小于0-营业开始时间小到当前时间，大于0-营业开始时间大于当前时间
                if (DateUtil.compareTime(dstChannelInfo.getBizStartTime(), currTime, SmartRouteParamConstant.FORMAT_DATE_TIME6) > 0) {
                    rglog.warn("通道<{}:{}>未到营业开始时间<{}>", dstChannelInfo.getDstChannelId(), dstChannelInfo.getDstChannelName(), dstChannelInfo.getBizStartTime());
                    return false;
                }
                rglog.debug("通道<{}:{}>营业开始时间<{}>检查通过", dstChannelInfo.getDstChannelId(), dstChannelInfo.getDstChannelName(), dstChannelInfo.getBizStartTime());
            } else {
                rglog.debug("通道<{}:{}>营业开始时间为*或者空<{}>不检查", dstChannelInfo.getDstChannelId(), dstChannelInfo.getDstChannelName(), dstChannelInfo.getBizStartTime());
            }
        }

        if (!StringUtil.isNullorEmpty(dstTxnAuthCfg.getSupportEndTime()) && !SmartRouteParamConstant.TIME_ALL.equals(dstTxnAuthCfg.getSupportEndTime())) {
            //营业结束时间 *不检查 表示到24点
            //0-相等，小于0-营业截止时间小到当前时间，大于0-营业截止时间大于当前时间
            if (DateUtil.compareTime(dstTxnAuthCfg.getSupportEndTime(), currTime, SmartRouteParamConstant.FORMAT_DATE_TIME6) < 0) {
                rglog.warn("通道交易<{}:{}>当前<{}>已过营业截止时间<{}>", dstTxnAuthCfg.getMsgDstId(), dstTxnAuthCfg.getTxnName(), currTime, dstTxnAuthCfg.getSupportEndTime());
                return false;
            }
            rglog.debug("通道交易<{}:{}>当前<{}>营业截止时间<{}>检查通过", dstTxnAuthCfg.getMsgDstId(), dstTxnAuthCfg.getTxnName(), currTime, dstTxnAuthCfg.getSupportEndTime());
        } else {
            rglog.debug("通道交易<{}:{}>当前<{}>营业截止时间为<{}>不检查通道交易，检查通道", dstTxnAuthCfg.getMsgDstId(), dstTxnAuthCfg.getTxnName(), currTime, dstTxnAuthCfg.getSupportEndTime());
            //通道存在开始时间则检查
            if (!StringUtil.isNullorEmpty(dstChannelInfo.getBizEndTime()) && !SmartRouteParamConstant.TIME_ALL.equals(dstChannelInfo.getBizEndTime())) {
                //0-相等，小于0-营业开始时间小到当前时间，大于0-营业开始时间大于当前时间
                if (DateUtil.compareTime(dstChannelInfo.getBizEndTime(), currTime, SmartRouteParamConstant.FORMAT_DATE_TIME6) < 0) {
                    rglog.warn("通道<{}:{}>已过营业截止时间<{}>", dstChannelInfo.getDstChannelId(), dstChannelInfo.getDstChannelName(), dstChannelInfo.getBizEndTime());
                    return false;
                }
                rglog.debug("通道<{}:{}>营业截止时间<{}>检查通过", dstChannelInfo.getDstChannelId(), dstChannelInfo.getDstChannelName(), dstChannelInfo.getBizEndTime());
            } else {
                rglog.debug("通道<{}:{}>营业截止时间为*或者空<{}>不检查", dstChannelInfo.getDstChannelId(), dstChannelInfo.getDstChannelName(), dstChannelInfo.getBizEndTime());
            }
        }
        return true;
    }

    /**
     * 检查限额
     *
     * @param dstChannelFilterModel 通过过滤对象
     * @param rglog                 日志句柄
     * @return true检查通过，false检查不通过
     * @throws Exception 其他失败和异常
     */
    private static boolean judgeAmtLimit(DstChannelFilterModel dstChannelFilterModel, CompleteRouteInfoBean completeRouteInfoBean, RgLogger rglog) throws Exception {
        if (!RouteTxnNumEnum.PAYMENT_SIGN.getTxnNum().equals(dstChannelFilterModel.getTxnNum())) {
            RouteTxnNumEnum routeTxnNumEnum = RouteTxnNumEnum.getInstanceFromTxnGroup(dstChannelFilterModel.getTxnGroup());
            if (routeTxnNumEnum == null) {
                return false;
            }
            String txnNum = routeTxnNumEnum.getTxnNum();
            rglog.debug("<机构:{}>,<交易:{}>,<金额:{}>", dstChannelFilterModel.getInstId(), txnNum, dstChannelFilterModel.getTransAmt());
            //如果是查询且交易金额为空则赋值交易金额为0
            if ((StringUtil.isNullorEmpty(dstChannelFilterModel.getTransAmt()) || StringUtil.isNullorEmpty(dstChannelFilterModel.getTransAmt().trim())) &&
                    RouteTxnNumEnum.ROUTER_QUERY.getTxnNum().equals(dstChannelFilterModel.getTxnNum())) {
                dstChannelFilterModel.setTransAmt("0.00");
            }
            PublicService publicService = new PublicServiceImpl();
            XmlTreeUtil xmlTreeUtil = new XmlTreeUtil();
            String sysSeqNum = xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.SYS_SEQ_NUM)+"1";
            xmlTreeUtil.setXmlTreeStringValue(TreeNodeConstant.SYS_SEQ_NUM, sysSeqNum);
            boolean checkResult = publicService.channelLimitCheck(dstChannelFilterModel.getInstId(), txnNum, dstChannelFilterModel.getTransAmt(),
                    dstChannelFilterModel.getDstChannelId(), completeRouteInfoBean.getDstTxnAuthCfg().getChannelTxn(), dstChannelFilterModel.getAcctType());
            if (!checkResult) {
                rglog.error("限额检查不通过");
                return false;
            }
        } else {
            rglog.debug("签约交易不检查限额");
        }
        return true;
    }

    /**
     * 统计限额，交易成功后调用
     *
     * @param rglog 日志句柄
     * @return true检查通过，false检查不通过
     */
    public static boolean statisAmtLimit(String instId, String srcTxnNum, String dstTxnNum, String dstChannelId, String acctType, String amt, RgLogger rglog) {
        if (StringUtil.isNullorEmpty(instId) || StringUtil.isNullorEmpty(dstTxnNum) ||
                StringUtil.isNullorEmpty(dstChannelId) || StringUtil.isNullorEmpty(amt)) {
            rglog.warn("请求信息缺失instId<{}>,dstTxnNum<{}>,dstChannelId<{}>,amt<{}>", instId, dstTxnNum, dstChannelId, amt);
            return false;
        }
        try {
            //校验交易限额
            PublicService publicService = new PublicServiceImpl();
            boolean checkResult = publicService.channelLimitStatis(instId, srcTxnNum, amt, dstChannelId, dstTxnNum, acctType);
            if (!checkResult) {
                rglog.warn("限额统计失败");
                return false;
            }
        } catch (Exception e) {
            rglog.warn("限额统计失败");
            rglog.warn(StringUtil.ExceptionToString(e));
            return false;
        }
        return true;
    }

    /**
     * 校验账户类型是否在支持列表中
     *
     * @param acctType     账户类型
     * @param acctTypeList 支持账户类型列表
     * @return boolean
     * @author xionglz
     * @date 2020-04-27
     **/
    private static boolean judgeAcctType(String acctType, String acctTypeList) {
        AcctTypeBitMapEnum acctTypeBitMapEnum = AcctTypeBitMapEnum.create(acctType);
        if (null == acctTypeBitMapEnum) {
            return false;
        }
        return acctTypeBitMapEnum.isSupport(acctTypeList);
    }

    /**
     * 判断对手行是否在支持列表
     * 若设置了对手行则为白名单，在白名单中则校验通过
     * 若不设置对手行则认为不限制（包括无数据和所有配置都无效的情况）
     *
     * @param openBankNo 开户行行号
     * @param instId     法人机构
     * @param channelId  通道编号
     * @return boolean
     * @author xionglz
     * @date 2020-04-27
     **/
    private static boolean judgeBankNo(String openBankNo, String instId, String channelId, String amt, RgLogger rglog)
            throws Exception {
        if (StringUtil.isNullorEmpty(openBankNo)) {
            rglog.error("请求银行行号为空");
            return false;
        }
        OpmsBankSupportCfgMapper opmsBankSupportCfgMapper = new OpmsBankSupportCfgMapperImpl();
        List<OpmsBankSupportCfgInfo> listOpmsBankSupportCfgInfo = opmsBankSupportCfgMapper.selectChannelSupport(
                instId, channelId, SmartRouteParamConstant.SUPPORT_BANK_LIST_TYPE);
        if (null == listOpmsBankSupportCfgInfo || listOpmsBankSupportCfgInfo.isEmpty()) {
            rglog.trace("对手行列表为空，不检查");
            return true;
        }
        boolean flag = false;
        for (OpmsBankSupportCfgInfo opmsBankSupportCfgInfo : listOpmsBankSupportCfgInfo) {
            if (SmartRouteParamConstant.YES.equals(opmsBankSupportCfgInfo.getRecordStatus())) {
                if (StringUtil.isNullorEmpty(opmsBankSupportCfgInfo.getBankNo()) || StringUtil.isNullorEmpty(opmsBankSupportCfgInfo.getBankNo().trim())) {
                    rglog.trace("<{}:{}>对手行行号为空忽略", opmsBankSupportCfgInfo.getBankNo(), opmsBankSupportCfgInfo.getBankName());
                    continue;
                }
                flag = true;
                if (opmsBankSupportCfgInfo.getBankNo().equals(openBankNo.trim())) {
                    //检查通道对手行的限额，只可以检查单笔限额，不可以检查累计限额，对手行日累计限额指的是个人用户在对手行的日累计限额
                    if (!StringUtil.isNullorEmpty(opmsBankSupportCfgInfo.getSingleLimitAmt()) &&
                            StringUtil.isNullorEmpty(opmsBankSupportCfgInfo.getSingleLimitAmt().trim())) {
                        if (AmountUtil.compare(amt, opmsBankSupportCfgInfo.getSingleLimitAmt().trim()) > 0) {
                            rglog.trace("<{}:{}>在对手行列表中,但是交易金额<{}>超过对手行限额<{}>检查不通过", openBankNo,
                                    opmsBankSupportCfgInfo.getBankName(), amt, opmsBankSupportCfgInfo.getSingleLimitAmt().trim());
                            return false;
                        }
                    }
                    rglog.trace("<{}:{}>在对手行列表中,检查通过", openBankNo, opmsBankSupportCfgInfo.getBankName());
                    return true;
                }
            }
        }
        //若没有有效数据则检查通过，若存在有效数据则检查失败
        rglog.trace("对手行列表中存在有效数据?<{}>", flag);
        return !flag;
    }

    /**
     * 通用判断存在记录状态及审核状态的数据是否有效
     *
     * @param recordStatus 记录状态
     * @param auditStatus  审核状态
     * @return boolean true 检查通过 false 检查不通过
     * @author xionglz
     * @date 2020-03-18
     */
    public static boolean judgeCommonRecordStatus(String recordStatus, String auditStatus) {
        if (RecordStatusEnum.RECORD_STATUS_OFFICIAL.getCode().equals(recordStatus)) {
            if (AuditStatusEnum.AUDIT_ADDITION_PASS.getCode().equals(auditStatus) ||
                    AuditStatusEnum.AUDIT_OPEN_PASS.getCode().equals(auditStatus) ||
                    AuditStatusEnum.AUDIT_MODIFY_PASS.getCode().equals(auditStatus)) {
                return true;
            }
        }
        return false;
    }

    public static CompleteRouteInfoBean getCompleteRouteInfoBean(String instId, String srcTxnNum, String txnGroup, String dstChannelId, RgLogger rglog) throws Exception {
        //根据机构id,源系统标识，交易码，业务分类查询通道服务调用配置表
        //查询redis，不存在或者失败再降级查询数据库
        ChannelCallCfgMapper channelCallCfgMapper = new ChannelCallCfgMapperImpl();
        List<ChannelCallCfg> ChannelCallCfgs = channelCallCfgMapper.selectChannelCallCfgByTxnNum(instId, SmartRouteParamConstant.IGRT, SmartRouteParamConstant.ALL, srcTxnNum, SmartRouteParamConstant.STRING_TWO_ZERO);
        Optional.ofNullable(ChannelCallCfgs).orElseThrow(() -> {
            rglog.error("获取交易码映射表失败");
            return new BizException(SmartRouteRspEnums.CONFIG_ERROR.getRespCode(), SmartRouteRspEnums.CONFIG_ERROR.getRespDesc());
        });
        Optional<ChannelCallCfg> channelCallCfg = ChannelCallCfgs.stream().filter(item -> item.getCallChannelId().equals(dstChannelId)).findFirst();
        if (channelCallCfg.isPresent()) {
            //获取通道信息
            DstChannelInfo dstChannelInfo = null;
            String dstChannelInfoKey = instId + dstChannelId;
            try {
                dstChannelInfo = JSON.parseObject(RedisUtil.hashGet(AppParamConstant.CHANNEL_ISS_INFO_CACHE, dstChannelInfoKey), DstChannelInfo.class);
            } catch (Exception e) {
                rglog.warn("redis中未查询到key<{}>通道信息", dstChannelInfoKey);
            }
            if (null == dstChannelInfo) {
                DstChannelInfoMapper dstChannelInfoMapper = new DstChannelInfoMapperImpl();
                dstChannelInfo = dstChannelInfoMapper.selectDstChannelInfoByPrimaryKey(instId, dstChannelId);
            }
            if (null == dstChannelInfo) {
                //未配置该通道
                rglog.error("该通道<{}：{}：{}>未配置通道信息", instId, dstChannelId);
                throw new BizException(SmartRouteRspEnums.CONFIG_ERROR.getRespCode(), SmartRouteRspEnums.CONFIG_ERROR.getRespDesc());
            }
            if (!judgeDstChannel(dstChannelInfo, rglog)) {
                rglog.error("该通道<{}：{}：{}>权限检查是吧", instId, dstChannelId);
                throw new BizException(SmartRouteRspEnums.NO_AUTH_ERROR.getRespCode(), SmartRouteRspEnums.NO_AUTH_ERROR.getRespDesc());
            }
            //获取通道交易权限信息
            DstTxnAuthCfg dstTxnAuthCfg = null;
            String dstTxnAuthKey = SmartRouteParamConstant.ROUTE_CONF_DST_TXN_AUTH + ":" + instId + ":" + dstChannelId + ":" + channelCallCfg.get().getCallChannelTxn();
            try {
                dstTxnAuthCfg = JSON.parseObject(RedisUtil.onceGet(dstTxnAuthKey), DstTxnAuthCfg.class);
            } catch (Exception e) {
                rglog.warn("redis中未查询到key<{}>通道交易权限信息", dstTxnAuthKey);
            }
            if (null == dstTxnAuthCfg) {
                //查询数据库
                DstTxnAuthCfgMapper dstTxnAuthCfgMapper = new DstTxnAuthCfgMapperImpl();
                dstTxnAuthCfg = dstTxnAuthCfgMapper.selectDstTxnAuthCfgByPrimaryKey(instId, dstChannelId, channelCallCfg.get().getCallChannelTxn());
            }
            if (null == dstTxnAuthCfg) {
                rglog.error("该通道<{}：{}：{}>没有配置支持智能路由的通道交易", instId, dstChannelId, channelCallCfg.get().getCallChannelTxn());
                throw new BizException(SmartRouteRspEnums.CONFIG_ERROR.getRespCode(), SmartRouteRspEnums.CONFIG_ERROR.getRespDesc());
            }
            DstChannelFilterModel dstChannelFilterModel = new DstChannelFilterModel();
            dstChannelFilterModel.setTxnGroup(txnGroup);
            dstChannelFilterModel.setDstChannelId(dstChannelId);
            dstChannelFilterModel.setInstId(instId);
            if (!judgeTxnAuth(dstChannelFilterModel, dstTxnAuthCfg, rglog)) {
                rglog.error("该通道<{}：{}：{}>权限检查是吧", instId, dstChannelId);
                throw new BizException(SmartRouteRspEnums.NO_AUTH_ERROR.getRespCode(), SmartRouteRspEnums.NO_AUTH_ERROR.getRespDesc());
            }
            //获取通道交易对应的实现封装
            //根据通道标识，通道交易码查询系统参数表获取对应实现类
            String type = SmartRouteParamConstant.PARAM_TYPE_PREFIX_CHANNEL_INSTANCE + dstChannelInfo.getDstChannelId();
            SysParamService sysParamService = new SysParamServiceImpl();
            SysParam sysParam = sysParamService.getSysParamInfo(dstChannelInfo.getInstId(), type, srcTxnNum);
            if (sysParam == null || cc.rengu.oltp.utility.util.StringUtil.isEmptyOrNull(sysParam.getParamValue()) || !SmartRouteParamConstant.YES.equalsIgnoreCase(sysParam.getParamStatus())) {
                rglog.error("根据通道标识<channelId:{}>，通道交易码<channelTxnId:{}>未找到机构<{}>客户化实现类或者通用法人实现类", type, srcTxnNum, dstChannelInfo.getInstId());
                throw new BizException(SmartRouteRspEnums.CONFIG_ERROR.getRespCode(), SmartRouteRspEnums.CONFIG_ERROR.getRespDesc());
            }
            CompleteRouteInfoBean completeRouteInfoBean = new CompleteRouteInfoBean(dstChannelInfo, channelCallCfg.get(), dstTxnAuthCfg);
            completeRouteInfoBean.setDstChannelTxnImplClassName(sysParam.getParamValue());
            return completeRouteInfoBean;
        } else {
            rglog.error("获取渠道交易<{}>,通道<{}>的通道服务调用配置失败", srcTxnNum, dstChannelId);
            throw new BizException(SmartRouteRspEnums.CONFIG_ERROR.getRespCode(), SmartRouteRspEnums.CONFIG_ERROR.getRespDesc());
        }
    }

}
